#ifndef SINGLETON_H
#define SINGLETON_H
//CRTP 实现单例模板：CRTP:奇异递归模板：
/*
1.基类是一个模板类
2.派生类继承该基类时，将派生类自身作为模板参数传递给基类
可实现静态多态：原理，基类模板中有一个成员函数（novirtual）f，其中f调用具体实现f_impl,子类继承基类模板，子类中也拥有f函数和f_impl，但是可以通过子类覆盖f_impl
但是f函数没有发生变换，里面呢依然是调用f_impl，所以就可以通过f接口发生多态。

与虚函数的动态多态不同的是，虚函数没有往里面座一层，虚函数不会将功能和实现分开来，而是直接让你继承重写
静态多态则是将功能和实现分开，功能负责之前的接口的功能，实现则负责之前的"多态"部分。从而多态。

也就是说，打个比方，比如你希望实现一个打印字符串的功能，使用虚函数，就是使用同一个接口print,并且在接口中根据类实现各自的同的功能

但是如果你使用静态多态，就要这样做了，将print分成：print接口和print_impl实现接口，所有的子类都会重载print_impl，但是print
是统一的，是不变的，通过print调用了print_impl从而发生多态了。
*/

/*
 *如何使用CRTP实现静态多态：类比于继承
 *要发生静态多态的子类：1。继承于基类。2.把自己传进基类3.重写impl函数，调用fun发生静态多态
 *基类：fun函数：强制类型转换到子类，调用子类impl函数。impl函数供子类覆盖，或者重写(避免)
*/
#include <memory>
#include <mutex>
#include <iostream>
using namespace std;
template <typename T>
class Singleton {
protected:
    Singleton() = default;
    Singleton(const Singleton<T>&) = delete;
    Singleton& operator=(const Singleton<T>& st) = delete;

    static std::shared_ptr<T> _instance;
public:

    //这个其实就是类似于fun函数接口，用于发生静态多态的，里面其实有具体实现，就是创建了一个instance，根据子类类型创建的智能指针。
    static std::shared_ptr<T> GetInstance() {
        static std::once_flag s_flag;
        std::call_once(s_flag, [&]() {
            _instance = shared_ptr<T>(new T);
        });

        return _instance;
    }
    void PrintAddress() {
        std::cout << _instance.get() << endl;
    }
    ~Singleton() {
        std::cout << "this is singleton destruct" << std::endl;
    }
};

template <typename T>
std::shared_ptr<T> Singleton<T>::_instance = nullptr;




#endif // SINGLETON_H
